package com.sfpay.coreplatform.order.service.composite.impl;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sfpay.coreplatform.account.valueobject.dto.TallySerialQuery;
import com.sfpay.coreplatform.account.valueobject.dto.Transfer;
import com.sfpay.coreplatform.account.valueobject.tmo.TallySerial;
import com.sfpay.coreplatform.order.common.enums.PayStatus;
import com.sfpay.coreplatform.order.persistence.dao.IPayOrderDao;
import com.sfpay.coreplatform.order.service.composite.ITask;
import com.sfpay.coreplatform.order.service.config.HandelConfig;
import com.sfpay.coreplatform.order.service.exception.OrderServiceException;
import com.sfpay.coreplatform.order.service.proxy.account.IAccountMgrProxyService;
import com.sfpay.coreplatform.order.service.validate.ValidateNULL;
import com.sfpay.coreplatform.order.valueobject.tmo.PayOrder;

public class CancelAccTask implements ITask {

	private final static Logger logger = LoggerFactory
			.getLogger(CancelAccTask.class);

	// 配置参数
	private HandelConfig config;
	// 支付dao
	private IPayOrderDao payOrderDao;
	// 支付订单
	private PayOrder payOrder;
	// 账务处理服务
	private IAccountMgrProxyService accountService;
	/**
	 * 记账对象
	 */
	private Transfer transfer;
	/**
	 * 记账是否要密码
	 */
	private boolean isAccPassword;

	public CancelAccTask(HandelConfig config, IPayOrderDao payOrderDao,
			IAccountMgrProxyService accountService, PayOrder payOrder,
			Transfer transfer, boolean isAccPassword) {
		this.config = config;
		this.payOrderDao = payOrderDao;
		this.payOrder = payOrder;
		this.transfer = transfer;
		this.accountService = accountService;
	}

	/**
	 * 查询是否已经记账
	 * 
	 * @return
	 */
	public boolean queryAccTransfer(String payNo) throws OrderServiceException {

		TallySerialQuery tallyQuery = new TallySerialQuery();

		tallyQuery.setPaymentOrderNo(payNo);// 付订单号

		List<TallySerial> allylist = accountService.findTallySerial(tallyQuery);
		if (allylist != null && allylist.size() > 0) {// 正常返回并有记账记录
			return true;
		}
		return false;
	}

	/**
	 * 增加支付订单
	 * 
	 * @return
	 * @throws OrderServiceException
	 */
	public String addPayOrder() {
		String payNo = payOrderDao.getNextPayNo();// 产生新的支付订单号
		payOrder.setPayNo(payNo);
		try {
			payOrderDao.addPayOrder(payOrder);
		} catch (Exception e) {
			logger.error("payNo：" + payNo + " asy save pay exception", e);
		}
		return payNo;
	}

	/**
	 * 记一笔销账
	 * 
	 * @param payno
	 * @return
	 * @throws OrderServiceException
	 */
	public boolean transfer(String payno) throws OrderServiceException {

		boolean result = false;
		try {
			transfer.setPaymentOrderNo(payno);// 用新的支付订单号
			if (isAccPassword) {// 记账要密码
				accountService.transfer(transfer);
			} else {
				accountService.transferWithoutPsw(transfer);
			}
			result = true;
		} catch (OrderServiceException e) {

		}
		return result;
	}

	/**
	 * 变更支付订单状态
	 * 
	 * @param payno
	 * @param checkStrike
	 */
	public void updateStatue(String payno, boolean checkStrike) {
		try {
			payOrderDao.updateState(payno, checkStrike ? PayStatus.SUCCESS
					: PayStatus.FAILURE, null);
		} catch (Exception e) {
			logger.error("payNo：" + payno + " asy update pay status exception",
					e);
		}
	}

	/**
	 * 轮询冲账处理
	 */
	public boolean cancelPollTransfer(String payno) {

		boolean checkStrike = false;

		for (int j = 0; j < config.getPollNumber(); j++) {
			try {
				checkStrike = this.queryAccTransfer(payno);
				if (checkStrike) {// 冲账成功
					break;
				}
			} catch (Exception e) {
				logger.error("payNo:" + payno + " query acc water exception ",
						e);
			}
			try {
				checkStrike = transfer(payno);// 冲账
				break;// 冲账无异常
			} catch (Exception e) {

				logger.error("payNo:" + payno
						+ "  acc handel balance  exception ", e);
			}
			try {
				Thread.sleep(config.getIntervalTime());// 间隔时间
			} catch (InterruptedException e) {
				logger.error(" thread interruptedexception", e);

			}
		}

		return checkStrike;
	}

	/**
	 * 轮询查询是否记账成功
	 * 
	 * @return
	 */
	public boolean queryPollTransfer() {
		boolean checkPosting = false;
		for (int i = 0; i < config.getPollNumber(); i++) {// 发送次数
			try {
				Thread.sleep(config.getIntervalTime());// 间隔时间
			} catch (InterruptedException e) {
				logger.error("thread interruptedexception", e);
			}
			try {
				checkPosting = this.queryAccTransfer(payOrder.getPayNo());// 查询是否成功
				break;// 正常返回
			} catch (OrderServiceException e) {
				// 只记录异常 不进行抛出处理
				logger.error("payNo:" + payOrder.getPayNo()
						+ " query acc water exception", e);
			}
		}
		return checkPosting;
	}

	@Override
	public void execute() {
		// 查询记账
		boolean checkPosting = queryPollTransfer();

		String payno = "";
		boolean checkStrike = false;
		if (checkPosting) {// 记账成功 进行冲账处理
			updateStatue(payOrder.getPayNo(), true);// 已经记账把原支付订单修改为成功
			payno = addPayOrder();// 增加支付订单
			if (!ValidateNULL.checkStringNull(payno)) {// 产生支付订单后才冲账
				checkStrike = cancelPollTransfer(payno);// 冲账
			}
			updateStatue(payno, checkStrike);// 冲账修改支付订单状态
		}

	}

}
